﻿///*
//SharpContent
//Copyright (c) 2002-2009, State of Montana

//Redistribution and use in source and binary forms, with or without modification,
//are permitted provided that the following conditions are met:

//1. Redistributions of source code must retain the above copyright notice,
//this list of conditions and the following disclaimer.
//2. Redistributions in binary form must reproduce the above copyright notice,
//this list of conditions and the following disclaimer in the documentation
//and/or other materials provided with the distribution.
//3. Neither the State of Montana nor the names of contributors may be used to endorse
//or promote products derived from this software without specific prior
//written permission.

//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
//EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
//SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
//TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
//BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
//DAMAGE.
//*/

(function() {
	function ItemSpecificationException(message) {
		this.name = 'ItemSpecificationException';
		this.message = message;
	}
	
	sharpRegistry.panes["default.item"] = function(url, item, displayElementId) {
		if (!item && item.length == 0)
			return undefined;
			
		var responses = new Array(item.getElementsByTagName('D:response')).flatten();
		if (!responses)
			return undefined;
			
		this.currentItem = responses.shift();
		this.version = (el = this.currentItem.getElementsByTagName('mc:version')) ? el[0] : '1';
		this.version = this.version.textContent ? this.version.textContent : this.version.text;
		if (responses.length > 0)
			this.childItems = responses;
		this.itemUrl = url;
		this.folderUrl = url.slice(0, url.lastIndexOf('/'));
		this.specification = sharplib.getItemSpecification(this.currentItem);
		if (!this.specification)
			throw new ItemSpecificationException('Item does not represent a valid item specification.');
		this.displayElementId = displayElementId;
		this.displayElement = (el = document.id(displayElementId)) ? el : new Element('div', {id: 'content'});
		this.mcsNS = this.currentItem.getAttribute('xmlns:mcs'); // FF: this.currentItem.lookupNamespaceURI('mcs')
		this.deq = new DeferredExecutionQueue();
		this.toHtml = function() {
			if (!this.specification)
				return new Element("h3", { text: "Error loading item specification" });

			// Build and populate pane display	
			var titlebar = new Element('h2', { id: 'item-title' });
			var itemName = this.currentItem.getElementsByTagName('mc:name')[0];
			if (itemName)
				titlebar.appendText(itemName.textContent ? itemName.textContent : itemName.text);

			var itemImage = new Element('div', { id: 'item-image' });
			
			var header = new Element('div', { id: 'header'});
			header.grab(new Element('div', { id: 'breadcrumbs', html: makeBreadCrumbs() }));
			header.grab(itemImage);
			header.grab(titlebar);
			
			var specFieldsForm = new Element('form');
			this.specification.each(function(spec) {
				var field = sharplib.fieldFromSpec(spec, item);
				if (field) {
					specFieldsForm.grab(field);
					specFieldsForm.grab(new Element('span', { 'class': 'ErrorMessage', 'text': 'Error Message:' }));
				}
			});

			var enclosure = new Element('div',
				{ 'id': 'accordion' }
			);
			enclosure.grab(new Element('h3', { text: 'Properties', 'class': 'toggler' }));
			
			var specFields = new Element('div', { id: 'properties', 'class': 'element'});
			specFields.grab(specFieldsForm);
			enclosure.grab(specFields);
			
			var baseUrl = window.location.href;
			baseUrl = baseUrl.charAt(baseUrl.length - 1) == "#" ? baseUrl.slice(0, baseUrl.length - 1) : baseUrl;
	
			var relationships = (new Array(this.currentItem.getElementsByTagName("mc:relation"))).flatten(),
				relationshipBlock = new Element('div', { 'id': 'relationships', 'class': 'element' });
			
			relationshipBlock.grab(new Element('input', {
				'type': 'button',
				'value': 'Visualize',
				'events': {
					'click': function() {
						var uri = new URI(window.location.href),
							href = this.currentItem.getElementsByTagName('D:href')[0],
							openTarget = uri.get('scheme') + "://" + uri.get('host') + '/jit_poc/graph.html?path=';
							openTarget = openTarget + (href.textContent ? href.textContent : href.text);
						window.open(openTarget);
					}.bind(this)
				},
				'styles': {
					'margin-left': '20px',
					'margin-top': '10px'
				}
			}));
			
			enclosure.grab(new Element('h3', { text: 'Relationships', 'class': 'toggler' }));
			
			this.relWidget = new sharpRegistry.widgets.relationship(relationships, this.deq);
			relationshipBlock.grab(this.relWidget);
			
			var referencedBy = (new Array(this.currentItem.getElementsByTagName('mc:reference'))).flatten().sort(function(a, b) {
					var atext = a.getAttribute('target'),
						btext = b.getAttribute('target');
						
					if (atext < btext)
						return -1;
					if (atext > btext)
						return 1;
					if (atext == btext)
						return 0;
				}),
				referencedByBlock = new Element('div', { 'id': 'references' }),
				referenceElement;
			
			referencedBy = referencedBy.sort(function(a, b) {
				var atext = a.getAttribute('source'),
					btext = b.getAttribute('source');
					
				if (atext < btext)
					return -1;
				if (atext > btext)
					return 1;
				if (atext == btext)
					return 0;
			});
			
			if (referencedBy && referencedBy.length > 0) {
				var referencedByList = new Element('ul', { 'id': 'referencedByList' }),
					source;
				referencedBy.each(function(reference) {
					source = reference.getAttribute('source');
					if (source) {
						referenceElement = new Element('li');
						referenceElement.grab(new Element('a', {
							'href': source,
							'text': source.indexOf(sharpbar.applicationUrl) < 0 ? source : source.slice(sharpbar.applicationUrl.length)
						}));
						referencedByList.grab(referenceElement);
					}
				});
				
				relationshipBlock.grab(new Element('h4', { 
					'text': 'Items that reference this item:', 
					'styles': {
						'padding-left': '20px'
					}
				}));	
				referencedByBlock.grab(referencedByList);
				relationshipBlock.grab(referencedByBlock);
			}
			
			enclosure.grab(relationshipBlock);
			
			// TODO: Add widget lookup if we're going to have more than this for optional panes based on an item's children.
			// TODO: Make the interface/client distinction less frail.
			if (this.childItems && this.childItems.length > 0) {
				var networkInterfaceWidget = new sharpRegistry.widgets.networkInterface(this.childItems),
					clientProviderId = 'cfac2c18-f4a8-4aff-91e7-194e1f9c25cd',
					resourceProviderId = (el = this.currentItem.getElementsByTagName('mc:resourceprovider')) ? el[0] : null;
					
				if(resourceProviderId)
					resourceProviderId = resourceProviderId.textContent ? resourceProviderId.textContent : resourceProviderId.text;
					
				enclosure.grab(new Element('h3', { 'text': resourceProviderId == clientProviderId ? 'Clients' : 'Interfaces', 'class': 'toggler' }));
				enclosure.grab(networkInterfaceWidget);
			}
			
			var documentationForm = new Element('form', { 'id': 'documentationForm' });
			
			var mimeType = (els = this.currentItem.getElementsByTagName('mc:mimetype')) ? els[0].firstChild.nodeValue : null;
			if (mimeType) {
				if (mimeType.indexOf('text/html') >= 0) {
					documentationForm.grab(sharplib.fieldMakers.textarea.makeLabel('documentation-box', ''));
					mc.getResource(this.itemUrl, null, function(results) {
						documentationForm.grab(sharplib.fieldMakers.textarea.makeField('documentation-box', results, new Hash({
							rows: 18,
							cols: 50
						})));
					});				
				}
				else  
					if (mimeType.slice(0, mimeType.indexOf('/')) == 'image') {
						documentationForm.grab(new Element('img', {
							'src': this.itemUrl
						}))
					}
					else {
						documentationForm.grab(new Element('a', {
							'href': this.itemUrl,
							'text': 'Click here to view resource'
						}));
					}
			}
			
			var documentation = new Element('div', { id: 'documentation', 'class': 'element'});
			documentation.grab(documentationForm);
			
			enclosure.grab(new Element('h3', { text: 'Documentation', 'class': 'toggler' }));
			enclosure.grab(documentation);

			var footer = new Element('div', {
				'id': 'footer'
			});
			
			footer.grab(new Element('input', {
				'id': 'save-item-button',
				'value': 'Save',
				'type': 'button',
				'events': {
					'click': function() {
						var validationExceptions = new Array(),
							setProps = new Hash(),
							removeProps = new Hash(),
							setXML,
							removeXML;
						if (this.specification) {
							this.specification.each(function(spec) {
								if (spec.fieldId) {
									field = document.id(spec.fieldName); // TODO: Should be spec.fieldId. Will take a bit of rejiggering though.
									if (field) {
										if (!field.value && spec.isRequired) 
											validationExceptions.push(new ValidationException(spec, 'isRequired'));
										if (spec.validationExpression && !field.value.match(spec.validationExpression)) 
											validationExceptions.push(new ValidationException(spec, 'validationExpression'));
										
										if (!setProps.has(spec.propertyKey)) 
											setProps[spec.propertyKey] = new Array();
										
										if(spec.fieldName == 'PublishedField') {
											setProps[spec.propertyKey].push(['innerText', field.checked ? "true" : "false"]);
										} else if (field.value) {
											setProps[spec.propertyKey].push(['innerText', field.value]);
										}
									}
								}
							});
							
/*
							if (validationExceptions.length > 0)
								throw validationExceptions;
*/
						}
						
						setXML = this.relWidget.relationshipsAdded ? this.relWidget.relationshipsAdded.join('\n') : '';
						removeXML = this.relWidget.relationshipsRemoved ? this.relWidget.relationshipsRemoved.join('\n') : '';
						mc.proppatch(this.itemUrl, function(xml){
							var documentation = CKEDITOR.instances['documentation-box'],
								location = xml.getElementsByTagName('D:href')[0],
								location = location.textContent ? location.textContent : location.text,
								responseDescription = xml.getElementsByTagName('D:responsedescription');
							
							if (responseDescription && responseDescription.length > 0) {
								responseDescription = responseDescription[0].textContent ? responseDescription[0].textContent : responseDescription[0].text;
								alert(responseDescription);
							}
							
							if (documentation) {
								mc.put(location, documentation.getData(), function(){
									window.location.href = location;
								});
							} else {
								window.location.href = location;
							}
						}.bind(this), setProps, null, this.mcsNS, setXML, removeXML, true);
						
					}.bind(this)
				}
			}));
			
			footer.grab(new Button('cancel-item-button', 'Cancel', {
				'click': function() {
					var content = document.id(this.displayElementId);
					if(content)
						content.empty();
				}.bind(this)
			}));			

			var scrollPane = (el = document.id('pane')) ? el :new Element('div', { 'id': 'pane' }),
				contentPane = new Element('div', { id: this.displayElementId });
			contentPane.grab(header);
			scrollPane.grab(enclosure);
			contentPane.grab(scrollPane);
			contentPane.grab(footer)
			return contentPane;
		};
		this.resize = function() {
			resizeContent();
		};
		this.display = function() {
			this.toHtml().replaces(this.displayElement);
			sharpRegistry.activePanes.item = this;

			// If this item is in a folder that isn't the current folder, change to the folder containing this item
			if (!sharpRegistry.activePanes.folder || this.folderUrl != sharpRegistry.activePanes.folder.folderUrl) {
				sharpbar.browser.openByUrl(this.folderUrl, ['D:displayname', 'mc:mimetype', 'mc:resourceprovider', 'mc:version', 'mc:published'], null, true);
			}

			mc.report(this.itemUrl, 'version', function (xmlReport) {
				var versionResponses = new Array(xmlReport.getElementsByTagName('D:response')).flatten(),
				versionControl = new Element('div', { 'id': 'version-control-div' }),
				versionSelector = new Element('select', { 
					'id': 'version-selector',
					'events': {
						'change': function() {
							var deleteButton = document.id('delete-draft-button'),
								isDraft = this[this.selectedIndex].isDraft;
								
							deleteButton.setStyle('display', isDraft ? 'inline' : 'none');
						}
					} 
				}),
				versionOptions = new Array(),
				draftSelected;

				if (versionResponses) {
					versionOptions = versionResponses.map(function(item) {
						var	id = item.getElementsByTagName('mc:id') ? item.getElementsByTagName('mc:id')[0].childNodes[0].nodeValue : '', 
						href = item.getElementsByTagName('D:href') ? item.getElementsByTagName('D:href')[0].childNodes[0].nodeValue : '',
						versionQuery = href.slice(href.lastIndexOf('?')),
						version = item.getElementsByTagName('D:version-name') ? item.getElementsByTagName('D:version-name')[0].childNodes[0].nodeValue.slice(1) : 'UNKNOWN',
						creator = item.getElementsByTagName('D:creator-displayname') ? item.getElementsByTagName('D:creator-displayname')[0].childNodes[0].nodeValue : '',
						versiondate = item.getElementsByTagName('mc:version-date') ? item.getElementsByTagName('mc:version-date')[0].childNodes[0].nodeValue : '',
						published = item.getElementsByTagName('mc:published')&& item.getElementsByTagName('mc:published')[0].childNodes[0].nodeValue == 'true' ? true : false,
						option = new Element('option', {
							'text': '[' + version + ']' + (published ? " Published" : ' Draft') + ' -- ' + creator + ' - ' + versiondate,
							'value': sharpbar.applicationUrl + "/" + id + versionQuery,
							'selected': version == this.version ? true : false
						});
						if (version == this.version)
							draftSelected = !published;
						option.isDraft = !published;
						versionSelector.grab(option);
					}.bind(this));
					versionControl.grab(versionSelector);
					versionControl.grab(new Button('version-selector-button', 'View', {
							'click': function() {
								window.location.href = document.id('version-selector').value; // TODO: Should we load inline or nav?
							}
						}
					));
					
					var deleteButton = new Button('delete-draft-button', 'Delete', {
						'click': function() {
							var selectedItem = document.id('version-selector'),
								itemUri = new URI(selectedItem.value),
								isDraft = selectedItem[selectedItem.selectedIndex].isDraft;
							
							if(isDraft) {
								mc.deleteItem(itemUri, function() {
									itemUri.clearData();
									window.location.href = itemUri.toString();
								});
							}
						}	
					});		
					deleteButton.setStyle('display', draftSelected ? 'inline' : 'none');
					versionControl.grab(deleteButton);
				}

				document.id('header').grab(versionControl);
			}.bind(this));

			updateBreadCrumbs(this.folderUrl);
			showBreadCrumbs('breadcrumbs');
	        var accordion = new Fx.Accordion($$('.toggler'),$$('.element'), {
                        opacity: 0,
                        onActive: function(toggler) { 
							toggler.setStyle('color', '#333'); 
							
							if (document.id('documentation-box')
								&& !document.id('cke_documentation-box') 
								&& toggler.innerHTML == "Documentation") {
								CKEDITOR.replace('documentation-box'); // defer this as far as possible. make sure we don't do it twice, as it throws an exception (!?!)
							}
						},
                        onBackground: function(toggler) { 
							toggler.setStyle('color', '#666'); 
						}         
        	});
			
			this.resize();
						// HACK: fiddle with accordion
/*
			var toggles = $$('.toggler'),
			    elements = $$('.element'),
				container = document.id('pane'),
				containerHeight = container.clientHeight;
			
			container.setStyle('overflow-y', 'hidden');
			totalToggleHeight = toggles.reduce(function(p, c) { return p + c.clientHeight; }, 0);
			elements.each(function(el) {
				el.setStyle('overflow-y', 'scroll');
				el.setStyle('height', containerHeight - totalToggleHeight);
			});
			this.displayElement.setStyle('display', 'block');
			this.deq.execute();
*/
		} .bind(this)
		
	};
})();